package concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * TODO 简单说明
 *
 * @author yangyang
 * @date 2017/7/5 17:28
 * @email kekecany@163.com
 */

class NewCar {
    private boolean waxOn = false;

    private Lock lock;

    private Condition condition;

    NewCar(Lock lock, Condition condition) {
        this.lock = lock;
        this.condition = condition;
    }

    void waxed() {
        lock.lock();
        try {
            waxOn = true;
            condition.signalAll();
        }finally {
            lock.unlock();
        }
    }

    void buffed() {
        lock.lock();
        try {
            waxOn = false;
            condition.signalAll();
        }finally {
            lock.unlock();
        }
    }

    void waitForWaxing() throws InterruptedException {
        lock.lock();
        try {
            while(!waxOn) {
                condition.await();
            }
        }finally {
            lock.unlock();
        }
    }

    void waitForBuffing() throws InterruptedException {
        lock.lock();
        try {
            while (waxOn) {
                condition.await();
            }
        } finally {
            lock.unlock();
        }
    }
}

class NewWaxOn implements Runnable {

    private NewCar newCar;

    NewWaxOn(NewCar newCar) {
        this.newCar = newCar;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                newCar.waitForBuffing();
                System.out.println("wax on!");
                TimeUnit.MILLISECONDS.sleep(200);
                newCar.waxed();
            }
        } catch (InterruptedException e) {
            System.out.println("exit wax on via interruption");
        }
        System.out.println("end wax on task");
    }
}

class NewWaxOff implements Runnable {

    private NewCar newCar;

    NewWaxOff(NewCar newCar) {
        this.newCar = newCar;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                newCar.waitForWaxing();
                System.out.println("wax off!");
                newCar.buffed();
            }
        } catch (InterruptedException e) {
            System.out.println("exit wax off via interruption");
        }
        System.out.println("end wax off task");
    }
}

public class WaxOMaticCondition {

    public static void main(String[] args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        NewCar newCar = new NewCar(lock, condition);
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.execute(new NewWaxOn(newCar));
        executorService.execute(new NewWaxOff(newCar));
        TimeUnit.SECONDS.sleep(5);
        executorService.shutdownNow();
    }

}